package com.xp.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xp.utils.Result;
import com.xp.dto.NodeDefinitionDTO;
import com.xp.dto.NodeDefinitionRequest;
import com.xp.dto.NodeQueryRequest;
import com.xp.service.NodeDefinitionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;

/**
 * 节点定义控制器
 * 提供节点定义的REST API接口
 *
 * @author xp
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/node-definitions")
@RequiredArgsConstructor
@Validated
@Tag(name = "节点定义管理", description = "节点定义的增删改查、状态管理、版本控制等接口")
public class NodeDefinitionController {

    private final NodeDefinitionService nodeDefinitionService;

    /**
     * 分页查询节点定义列表
     *
     * @param request 查询参数
     * @return 分页结果
     */
    @Operation(summary = "分页查询节点定义列表")
    @GetMapping("/page")
    public Result<IPage<NodeDefinitionDTO>> getNodeDefinitionPage(@Valid NodeQueryRequest request) {
        try {
            IPage<NodeDefinitionDTO> result = nodeDefinitionService.getNodeDefinitionPage(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID查询节点定义详情
     *
     * @param id 节点ID
     * @return 节点定义详情
     */
    @Operation(summary = "根据ID查询节点定义详情")
    @GetMapping("/{id}")
    public Result<NodeDefinitionDTO> getNodeDefinitionById(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id) {
        try {
            NodeDefinitionDTO result = nodeDefinitionService.getNodeDefinitionById(id);
            if (result == null) {
                return Result.error("节点定义不存在");
            }
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询节点定义详情失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据节点编码查询节点定义
     *
     * @param nodeCode 节点编码
     * @return 节点定义
     */
    @Operation(summary = "根据节点编码查询节点定义")
    @GetMapping("/code/{nodeCode}")
    public Result<NodeDefinitionDTO> getNodeDefinitionByCode(
            @Parameter(description = "节点编码", required = true) @PathVariable @NotEmpty String nodeCode) {
        try {
            NodeDefinitionDTO result = nodeDefinitionService.getNodeDefinitionByCode(nodeCode);
            if (result == null) {
                return Result.error("节点定义不存在");
            }
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询节点定义失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 创建节点定义
     *
     * @param request 节点定义请求参数
     * @return 创建的节点定义
     */
    @Operation(summary = "创建节点定义")
    @PostMapping
    public Result<NodeDefinitionDTO> createNodeDefinition(@Valid @RequestBody NodeDefinitionRequest request) {
        try {
            NodeDefinitionDTO result = nodeDefinitionService.createNodeDefinition(request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("创建节点定义失败", e);
            return Result.error("创建失败: " + e.getMessage());
        }
    }

    /**
     * 更新节点定义
     *
     * @param id 节点ID
     * @param request 节点定义请求参数
     * @return 更新的节点定义
     */
    @Operation(summary = "更新节点定义")
    @PutMapping("/{id}")
    public Result<NodeDefinitionDTO> updateNodeDefinition(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id,
            @Valid @RequestBody NodeDefinitionRequest request) {
        try {
            NodeDefinitionDTO result = nodeDefinitionService.updateNodeDefinition(id, request);
            return Result.success(result);
        } catch (Exception e) {
            log.error("更新节点定义失败", e);
            return Result.error("更新失败: " + e.getMessage());
        }
    }

    /**
     * 删除节点定义
     *
     * @param id 节点ID
     * @return 是否删除成功
     */
    @Operation(summary = "删除节点定义")
    @DeleteMapping("/{id}")
    public Result<Boolean> deleteNodeDefinition(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id) {
        try {
            Boolean result = nodeDefinitionService.deleteNodeDefinition(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("删除节点定义失败", e);
            return Result.error("删除失败: " + e.getMessage());
        }
    }

    /**
     * 批量删除节点定义
     *
     * @param ids 节点ID列表
     * @return 是否删除成功
     */
    @Operation(summary = "批量删除节点定义")
    @DeleteMapping("/batch")
    public Result<Boolean> batchDeleteNodeDefinitions(
            @Parameter(description = "节点ID列表", required = true) @RequestBody @NotEmpty List<Long> ids) {
        try {
            Boolean result = nodeDefinitionService.batchDeleteNodeDefinitions(ids);
            return Result.success(result);
        } catch (Exception e) {
            log.error("批量删除节点定义失败", e);
            return Result.error("删除失败: " + e.getMessage());
        }
    }

    /**
     * 启用节点定义
     *
     * @param id 节点ID
     * @return 是否启用成功
     */
    @Operation(summary = "启用节点定义")
    @PutMapping("/{id}/enable")
    public Result<Boolean> enableNodeDefinition(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id) {
        try {
            Boolean result = nodeDefinitionService.enableNodeDefinition(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("启用节点定义失败", e);
            return Result.error("启用失败: " + e.getMessage());
        }
    }

    /**
     * 禁用节点定义
     *
     * @param id 节点ID
     * @return 是否禁用成功
     */
    @Operation(summary = "禁用节点定义")
    @PutMapping("/{id}/disable")
    public Result<Boolean> disableNodeDefinition(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id) {
        try {
            Boolean result = nodeDefinitionService.disableNodeDefinition(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("禁用节点定义失败", e);
            return Result.error("禁用失败: " + e.getMessage());
        }
    }

    /**
     * 批量更新节点状态
     *
     * @param request 批量更新请求
     * @return 是否更新成功
     */
    @Operation(summary = "批量更新节点状态")
    @PutMapping("/batch/status")
    public Result<Boolean> batchUpdateStatus(@RequestBody Map<String, Object> request) {
        try {
            @SuppressWarnings("unchecked")
            List<Long> ids = (List<Long>) request.get("ids");
            Integer status = (Integer) request.get("status");
            
            if (ids == null || ids.isEmpty()) {
                return Result.error("节点ID列表不能为空");
            }
            if (status == null) {
                return Result.error("状态不能为空");
            }
            
            Boolean result = nodeDefinitionService.batchUpdateStatus(ids, status);
            return Result.success(result);
        } catch (Exception e) {
            log.error("批量更新节点状态失败", e);
            return Result.error("更新失败: " + e.getMessage());
        }
    }

    /**
     * 复制节点定义
     *
     * @param sourceId 源节点ID
     * @param request 复制请求参数
     * @return 复制的节点定义
     */
    @Operation(summary = "复制节点定义")
    @PostMapping("/{sourceId}/copy")
    public Result<NodeDefinitionDTO> copyNodeDefinition(
            @Parameter(description = "源节点ID", required = true) @PathVariable @NotNull Long sourceId,
            @RequestBody Map<String, String> request) {
        try {
            String newNodeCode = request.get("nodeCode");
            String newNodeName = request.get("nodeName");
            String newVersion = request.get("version");
            
            if (newNodeCode == null || newNodeCode.trim().isEmpty()) {
                return Result.error("新节点编码不能为空");
            }
            if (newNodeName == null || newNodeName.trim().isEmpty()) {
                return Result.error("新节点名称不能为空");
            }
            if (newVersion == null || newVersion.trim().isEmpty()) {
                newVersion = "1.0.0";
            }
            
            NodeDefinitionDTO result = nodeDefinitionService.copyNodeDefinition(sourceId, newNodeCode, newNodeName, newVersion);
            return Result.success(result);
        } catch (Exception e) {
            log.error("复制节点定义失败", e);
            return Result.error("复制失败: " + e.getMessage());
        }
    }

    /**
     * 根据节点类型查询节点定义列表
     *
     * @param nodeType 节点类型
     * @return 节点定义列表
     */
    @Operation(summary = "根据节点类型查询节点定义列表")
    @GetMapping("/type/{nodeType}")
    public Result<List<NodeDefinitionDTO>> getNodeDefinitionsByType(
            @Parameter(description = "节点类型", required = true) @PathVariable @NotEmpty String nodeType) {
        try {
            List<NodeDefinitionDTO> result = nodeDefinitionService.getNodeDefinitionsByType(nodeType);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据节点分类查询节点定义列表
     *
     * @param category 节点分类
     * @return 节点定义列表
     */
    @Operation(summary = "根据节点分类查询节点定义列表")
    @GetMapping("/category/{category}")
    public Result<List<NodeDefinitionDTO>> getNodeDefinitionsByCategory(
            @Parameter(description = "节点分类", required = true) @PathVariable @NotEmpty String category) {
        try {
            List<NodeDefinitionDTO> result = nodeDefinitionService.getNodeDefinitionsByCategory(category);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 查询所有启用的节点定义
     *
     * @return 节点定义列表
     */
    @Operation(summary = "查询所有启用的节点定义")
    @GetMapping("/enabled")
    public Result<List<NodeDefinitionDTO>> getEnabledNodeDefinitions() {
        try {
            List<NodeDefinitionDTO> result = nodeDefinitionService.getEnabledNodeDefinitions();
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询启用节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 查询系统内置节点定义
     *
     * @return 节点定义列表
     */
    @Operation(summary = "查询系统内置节点定义")
    @GetMapping("/system")
    public Result<List<NodeDefinitionDTO>> getSystemNodeDefinitions() {
        try {
            List<NodeDefinitionDTO> result = nodeDefinitionService.getSystemNodeDefinitions();
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询系统节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 查询自定义节点定义
     *
     * @return 节点定义列表
     */
    @Operation(summary = "查询自定义节点定义")
    @GetMapping("/custom")
    public Result<List<NodeDefinitionDTO>> getCustomNodeDefinitions() {
        try {
            List<NodeDefinitionDTO> result = nodeDefinitionService.getCustomNodeDefinitions();
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询自定义节点定义列表失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 获取节点分类列表
     *
     * @return 分类列表
     */
    @Operation(summary = "获取节点分类列表")
    @GetMapping("/categories")
    public Result<List<String>> getNodeCategories() {
        try {
            List<String> result = nodeDefinitionService.getNodeCategories();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取节点分类列表失败", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取节点类型列表
     *
     * @return 类型列表
     */
    @Operation(summary = "获取节点类型列表")
    @GetMapping("/types")
    public Result<List<String>> getNodeTypes() {
        try {
            List<String> result = nodeDefinitionService.getNodeTypes();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取节点类型列表失败", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取节点定义统计信息
     *
     * @return 统计信息
     */
    @Operation(summary = "获取节点定义统计信息")
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getNodeDefinitionStatistics() {
        try {
            Map<String, Object> result = nodeDefinitionService.getNodeDefinitionStatistics();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取节点定义统计信息失败", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取分类统计信息
     *
     * @return 分类统计信息
     */
    @Operation(summary = "获取分类统计信息")
    @GetMapping("/statistics/category")
    public Result<List<Map<String, Object>>> getCategoryStatistics() {
        try {
            List<Map<String, Object>> result = nodeDefinitionService.getCategoryStatistics();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取分类统计信息失败", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 验证节点编码是否可用
     *
     * @param nodeCode 节点编码
     * @param excludeId 排除的ID（可选）
     * @return 是否可用
     */
    @Operation(summary = "验证节点编码是否可用")
    @GetMapping("/validate/code")
    public Result<Boolean> validateNodeCode(
            @Parameter(description = "节点编码", required = true) @RequestParam @NotEmpty String nodeCode,
            @Parameter(description = "排除的ID") @RequestParam(required = false) Long excludeId) {
        try {
            Boolean result = nodeDefinitionService.validateNodeCode(nodeCode, excludeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("验证节点编码失败", e);
            return Result.error("验证失败: " + e.getMessage());
        }
    }

    /**
     * 验证节点配置Schema
     *
     * @param request Schema验证请求
     * @return 验证结果
     */
    @Operation(summary = "验证节点配置Schema")
    @PostMapping("/validate/schema")
    public Result<Boolean> validateSchema(@RequestBody Map<String, String> request) {
        try {
            String schema = request.get("schema");
            if (schema == null) {
                return Result.error("Schema不能为空");
            }
            
            Boolean result = nodeDefinitionService.validateSchema(schema);
            return Result.success(result);
        } catch (Exception e) {
            log.error("验证Schema失败", e);
            return Result.error("验证失败: " + e.getMessage());
        }
    }

    /**
     * 测试节点定义
     *
     * @param id 节点ID
     * @param testData 测试数据
     * @return 测试结果
     */
    @Operation(summary = "测试节点定义")
    @PostMapping("/{id}/test")
    public Result<Map<String, Object>> testNodeDefinition(
            @Parameter(description = "节点ID", required = true) @PathVariable @NotNull Long id,
            @RequestBody Map<String, Object> testData) {
        try {
            Map<String, Object> result = nodeDefinitionService.testNodeDefinition(id, testData);
            return Result.success(result);
        } catch (Exception e) {
            log.error("测试节点定义失败", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }

    /**
     * 导出节点定义
     *
     * @param ids 节点ID列表（可选）
     * @return 导出数据
     */
    @Operation(summary = "导出节点定义")
    @PostMapping("/export")
    public Result<String> exportNodeDefinitions(@RequestBody(required = false) List<Long> ids) {
        try {
            String result = nodeDefinitionService.exportNodeDefinitions(ids);
            return Result.success(result);
        } catch (Exception e) {
            log.error("导出节点定义失败", e);
            return Result.error("导出失败: " + e.getMessage());
        }
    }

    /**
     * 导入节点定义
     *
     * @param request 导入请求
     * @return 导入结果
     */
    @Operation(summary = "导入节点定义")
    @PostMapping("/import")
    public Result<Map<String, Object>> importNodeDefinitions(@RequestBody Map<String, String> request) {
        try {
            String data = request.get("data");
            if (data == null || data.trim().isEmpty()) {
                return Result.error("导入数据不能为空");
            }
            
            Map<String, Object> result = nodeDefinitionService.importNodeDefinitions(data);
            return Result.success(result);
        } catch (Exception e) {
            log.error("导入节点定义失败", e);
            return Result.error("导入失败: " + e.getMessage());
        }
    }
}